/*
** Konami Gradius III.
** This is just a slight variation on the 7232-based hardware,
** featuring a larger ROM.
**
** This runs like crap on the current scheduler.
*/

#include "smse2kincludes.h"
#include "SoundDeviceFactory.h"
#include "CPUFactory.h"
#include "G3Driver.h"

int CG3Driver::Load(const char* fn) {
	// Open the ROMs up
	FILE_HANDLE sample_rom = filesystem.OpenFile("945_a10.b15",FSYS_PERMISSION_READ);
	FILE_HANDLE code_rom   = filesystem.OpenFile("945_m05.d9", FSYS_PERMISSION_READ);
	
	if (!code_rom) return 1;

	this->code = new CMemory;
	UINT32 fsize = filesystem.GetFileSize(code_rom);
	code->AllocMemory(fsize);

	this->samples = new CMemory;
	fsize = filesystem.GetFileSize(sample_rom);
	samples->AllocMemory(fsize);

	filesystem.Read(code_rom, code->GetRawMemory(), fsize);
	filesystem.Read(sample_rom, samples->GetRawMemory(), fsize);
	filesystem.CloseFile(code_rom);
	filesystem.CloseFile(sample_rom);
	


	return 0;
}

int CG3Driver::Init(CHardware *hard) {
	this->konami = SoundDeviceFactory("K007232");
	this->ym = SoundDeviceFactory("YM2151");
	this->z80 = CPUFactory("Z80");
	
	z80->Init(CLOCK_MHZ(8)); 
	z80->AssignMMU(0, this); // because I can.
	ym->Init(hard->mixer, 3579545);
	konami->Init(hard->mixer, 3579545);
	memcpy(memspace,code->GetRawMemory(),0xf000);

	konami->SetRom(0, samples);
	hard->AddCpu(z80);

	
	hard->ChangeScheduler(1.0 / 120.0, 1.0 / 240.0);
	return 0;
}

void CG3Driver::SetSubsong(int song) {
	memspace[0xf010] = 0x80; //song & 0xff;
	z80->Interrupt(0, HOLD_LINE);
}

void CG3Driver::FreeUnusedResources() {

}

void CG3Driver::Close() {

}

/********** MMU **********/

void CG3Driver::Write8(UINT64 offset, UINT8 data) {
	
	if (offset == 0xf000) { // 7232 bankswitch
		konami->Write(0xfffe, ((data >> 0) & 0x03));
		konami->Write(0xffff, ((data >> 2) & 0x03));
	}
	
	
	if ((offset >= 0xf020) && (offset <= 0xf02d)) konami->Write(offset & 0xf, data);
	if ((offset == 0xf030) || (offset == 0xf031)) ym->Write(offset & 1, data);
	
	memspace[offset & 0xffff] = data;
}

UINT8 CG3Driver::Read8(UINT64 offset) {

	if ((offset >= 0xf020) && (offset <= 0xf02d)) return konami->Read(offset & 0xf);
	if ((offset == 0xf030) || (offset == 0xf031)) return ym->Read(offset & 1);

	return memspace[offset & 0xffff];
}

DRIVER_DOES_NOT_SUPPORT_FILETYPES(CG3Driver);
DRIVER_FACTORY("gradius3","Gradius 3 Test",1,CG3Driver);